package com.example.my_self_view.list

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Paint.FontMetricsInt
import android.graphics.Rect
import android.util.AttributeSet
import android.util.TypedValue
import android.view.MotionEvent
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class ProvinceListView: RecyclerView {

    private val letterPaint by lazy { Paint() }
    private val tipPaint by lazy { Paint() }
    private val letterRect by lazy { Rect() }
    private val tipRect by lazy { Rect() }
    private val letterSize = 16
    private val tipSize = 40
    private var isUp = false

    private lateinit var fontMetricsInt: FontMetricsInt
    private var dx: Float = 0f
    private val startMap = hashMapOf<Float, Char>()
    private var currentKey = 0f
    private var currentChar = '?'

    constructor(context: Context): this(context, null) {}
    constructor(context: Context, attrs: AttributeSet?): this(context, attrs, 0) {}
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr){
        letterPaint.apply {
            isAntiAlias = true
            isDither = true
            textSize = spToPx(letterSize.toFloat())
            textAlign = Paint.Align.CENTER
            color = Color.parseColor("#6E6E6E")
        }

        tipPaint.apply {
            isAntiAlias = true
            isDither = true
            textSize = spToPx(tipSize.toFloat())
            color = Color.parseColor("#00BF7E")
        }
    }

    private fun spToPx(value: Float): Float {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, resources.displayMetrics)
    }

    private fun dipToPx(value: Float): Float {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, resources.displayMetrics)
    }

    // A, B, C // 3h+2d

    override fun dispatchDraw(canvas: Canvas) {
        super.dispatchDraw(canvas)
        canvas.save()
        // 获取字母的宽高
        letterPaint.getTextBounds("A", 0, 1, letterRect)
        // 计算字母组的最中间的 baseline，字母组有可能是奇数，有可能是偶数
        dx = width - letterRect.width() - dipToPx(8f)
        fontMetricsInt = letterPaint.fontMetricsInt
        val dy = - (fontMetricsInt.top + fontMetricsInt.bottom) / 2
        val interval = dipToPx(15f)
        val baseInterval = letterRect.height() + interval
        // 1.奇数 baseline
        val oddBaseLine = height / 2 + dy

        /**
         * 计算偶数 baseline, H: RecycleView的高度, h: 一个字母的高度, d: 两个字母之间的间隔
         * start = H/2 - (2h+d)/2
         * end = start + h
         * 中位值 = (start + end) / 2
         * baseline = 中位值 + dy
         */
        val start = height / 2 - (2 * letterRect.height() + interval) / 2
        val end = start + letterRect.height()
        val midden = (start + end) / 2
        // 2.偶数 baseline
        val evenBaseLine = midden + dy

        /**
         * midden = evenBaseLine - dy
         * midden = (start + end) / 2
         * start = ((evenBaseLine - dy) * 2 - rect.height()) / 2
         */

        // 画所有字母
        for (c in 'M' downTo 'A') {
            val actualBSL = evenBaseLine - ('M' - c) * baseInterval
            canvas.drawText(c.toString(), dx, actualBSL, letterPaint)
            if (startMap.size <= 26) {
                val key = ((actualBSL - dy) * 2 - letterRect.height()) / 2
                startMap[key] = c
            }
        }
        for (c in 'N' .. 'Z') {
            val actualBSL = evenBaseLine + (c - 'M') * baseInterval
            canvas.drawText(c.toString(), dx, actualBSL, letterPaint)
            if (startMap.size <= 26) {
                val key = ((actualBSL - dy) * 2 - letterRect.height()) / 2
                startMap[key] = c
            }
        }
        canvas.restore()

        if (currentChar != '?' && !isUp) {
            canvas.save()
            // 画 RecyclerView 的 y 中位线
//        canvas.drawLine(0f, height/2f, width.toFloat(), height/2f, tipPaint)
            // 画 RecyclerView 的 x 中位线
//        canvas.drawLine(width/2f, 0f, width/2f, height.toFloat(), tipPaint)
            // 画 tip
            tipPaint.getTextBounds("A", 0, 1, tipRect)
            val tipFontMetricsInt = tipPaint.fontMetricsInt
            val tipDx = width/2f - tipRect.width()/2f
            val tipDy = - (tipFontMetricsInt.top + tipFontMetricsInt.bottom) / 2f
            val tipBaseLine = height/2f + tipDy
            canvas.drawText(currentChar.toString(), tipDx, tipBaseLine, tipPaint)
            canvas.restore()
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent): Boolean {
        when (event.action) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
                if (event.x in (dx - dipToPx(10f))..(dx + letterRect.width() + dipToPx(10f))) {
                    isUp = false
                    for (k in startMap.keys) {
                        if (event.y in k..(k + letterRect.height())) {
                            val c = startMap[k] ?: '?'
                            currentKey = k
                            currentChar = c
                            scrollToLetter(c)
                            break
                        }
                    }
                    return true
                }
            }
            MotionEvent.ACTION_UP -> {
                if (!isUp) {
                    isUp = true
                    invalidate()
                }
            }
        }
        return super.onTouchEvent(event)
    }

    private fun scrollToLetter(c: Char) {
        val layoutManager = this.layoutManager as LinearLayoutManager
        val adapter = this.adapter as ProvinceListAdapter
        val position = adapter.getPosition(Letter(c.toString()))
        layoutManager.scrollToPositionWithOffset(position, 0)
    }
}